#include "slavevieweffect.h"
#include "actorbase.h"
#include "drawable.h"
#include "transformableactor.h"
#include <osg\Node>
#include <osg\Camera>
#include "manipulatormanager.h"
#include "attachobjectmanipulator.h"
#include "pickmanager.h"
#include "effectcontainermanager.h"
#include "perspectiveview.h"
#include "datatypedefine.h"
#include "datamanager.h"
#include "actorfactory.h"
#include "layersmanager.h"
#include "singlelayeractor.h"
#include "cameraanimationactor.h"
#include "utility.h"
#include "cameraanimationmanipulator.h"

SlaveViewEffect::SlaveViewEffect(PublicGui::PerspectiveView* pv):_pv(pv),_accidentCameraAnimationIdle(true)
{
	_slaveCamera = new osg::Camera;
	_slaveCamera->setName(SLAVEVIEW_EFFECT_CAMERA);
	_manipulatorManager = new ControlCenter::ManipulatorManager(_pv->getViewer(),_pv->getScene());
}

SlaveViewEffect::~SlaveViewEffect()
{}

void SlaveViewEffect::buildPropertyMap()
{
	EffectBase::buildPropertyMap();
}

void SlaveViewEffect::setManipulatorType(const QString& type,CoreBase::ActorBase* lookat)
{
	_manipulatorManager->registerManipulator(type);
	_manipulatorType = type;
	_lookAtActor = lookat;
}

void SlaveViewEffect::frame(osg::ref_ptr<osgGA::GUIEventAdapter> ea,osgGA::GUIActionAdapter* aa)
{
	if(_manipulatorType == CLASS_MANIPULATOR_ATTACHOBJECT)
	{
		if(!_attachObjectEffect.valid())
		{
			_attachObjectEffect = new ControlCenter::AttachObjectEffect(
				_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_ATTACHOBJECT),_pv->getViewer()->getCamera());
		}
		if(_attachObjectEffect->isIdle())
		{
			_attachObjectEffect->setInitial(osg::Vec3(0,0,0),200,20,0);
			_attachObjectEffect->apply(_lookAtActor);
		}
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_ATTACHOBJECT)->handle(*ea,*aa);
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_ATTACHOBJECT)->updateCamera(*_slaveCamera);
	}
	else if(_manipulatorType ==CLASS_MANIPULATOR_CAMERAANIMATION)
	{
		if(!_accidentCameraAnimation.valid())
		{
			_accidentCameraAnimation = VrDataCore::DataManager::GetInstance().getActorFactory(
						)->createActorByDataType(CLASS_CAMERA_ANIMATION);
			_accidentCameraAnimation->setName("slavecameraanimation");
			dynamic_cast<VrDataCore::SingleLayerActor*>(VrDataCore::LayersManager::GetInstance(
					).getCameraAnimationLayer())->addChild(_accidentCameraAnimation);
		}
		if(_accidentCameraAnimationIdle)
		{
			dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->clear();
			QVector<osg::Vec3> r;
			getTaperedCurve(20,100,1,osg::PI/50.0f,osg::PI/9,r);
			dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->setWithActor(_lookAtActor);
			for(int i=0;i<r.size();++i)
			{
				osg::Vec3 eye = r.at(i);
				osg::Vec3 up = osg::Vec3(0,0,1);
				dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->setPlayMode(VrDataCore::CamreaAnimationBase::Loop);
				dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->addCameraAttitude(eye,
					osg::Vec3(0,0,0),up);
			}
			ActionData newdata;
			newdata._actionKey = ACTION_NOSWITCH_CAMERAANIMATION;
			newdata._dataType = "AnimationName";
			newdata._userDefineData = &QString("slavecameraanimation");
			_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->enableManipulator();
			dynamic_cast<ControlCenter::CameraAnimationManipulator*>(_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION))
				->setView(NULL);
			_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->setToolAction(&newdata);
			_accidentCameraAnimationIdle = false;
		}
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->handle(*ea,*aa);
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->updateCamera(*_slaveCamera);
	}
}

void SlaveViewEffect::apply(CoreBase::ActorBase* actor)
{
	if(!isIdle())
		return;
	_slaveCamera->setProjectionMatrix(_pv->getViewer()->getCamera()->getProjectionMatrix());
	_slaveCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
	_slaveCamera->setViewMatrix(_pv->getViewer()->getCamera()->getViewMatrix());
	_slaveCamera->setClearMask( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	_slaveCamera->setGraphicsContext(_pv->getViewer()->getCamera()->getGraphicsContext());
	_slaveCamera->setAllowEventFocus(false);
	_slaveCamera->setViewport(0,0,_pv->getViewer()->getCamera()->getViewport()->width()/4.0f,
		_pv->getViewer()->getCamera()->getViewport()->height()/4.0f);
	/*VrDataCore::EffectContainerManager::GetInstance().addEventCallback<SlaveViewEffect,osg::ref_ptr<osgGA::GUIEventAdapter>
		,osgGA::GUIActionAdapter*>(VrDataCore::EventType::EVENT_FRAME,&SlaveViewEffect::frame,this);*/
	_pv->getViewer()->addSlave(_slaveCamera);
	_pv->setThreadingModel(osgViewer::Viewer::SingleThreaded);
	//_slaveCamera->addUpdateCallback(new SlaveViewEffectCallback(this));
	_pv->getViewer()->getSlave(0)._updateSlaveCallback = new SlaveViewEffectCallback(this);
	//VrDataCore::EffectContainerManager::GetInstance().addEffectNode(_slaveCamera);
	VrDataCore::EffectBase::apply(actor);
}

void SlaveViewEffect::update()
{
	if(_manipulatorType == CLASS_MANIPULATOR_ATTACHOBJECT)
	{
		if(!_attachObjectEffect.valid())
		{
			_attachObjectEffect = new ControlCenter::AttachObjectEffect(
				_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_ATTACHOBJECT),_pv->getViewer()->getCamera());
		}
		if(_attachObjectEffect->isIdle())
		{
			_attachObjectEffect->setInitial(osg::Vec3(0,0,0),200,20,0);
			_attachObjectEffect->apply(_lookAtActor);
		}
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_ATTACHOBJECT)->frame();
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_ATTACHOBJECT)->updateCamera(*_slaveCamera);
	}
	else if(_manipulatorType ==CLASS_MANIPULATOR_CAMERAANIMATION)
	{
		if(!_accidentCameraAnimation.valid())
		{
			_accidentCameraAnimation = VrDataCore::DataManager::GetInstance().getActorFactory(
						)->createActorByDataType(CLASS_CAMERA_ANIMATION);
			_accidentCameraAnimation->setName("slavecameraanimation");
			dynamic_cast<VrDataCore::SingleLayerActor*>(VrDataCore::LayersManager::GetInstance(
					).getCameraAnimationLayer())->addChild(_accidentCameraAnimation);
		}
		if(_accidentCameraAnimationIdle)
		{
			dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->clear();
			QVector<osg::Vec3> r;
			getTaperedCurve(20,100,1,osg::PI/50.0f,osg::PI/9,r);
			dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->setWithActor(_lookAtActor);
			for(int i=0;i<r.size();++i)
			{
				osg::Vec3 eye = r.at(i);
				osg::Vec3 up = osg::Vec3(0,0,1);
				dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->setPlayMode(VrDataCore::CamreaAnimationBase::Loop);
				dynamic_cast<VrDataCore::CamreaAnimationActor*>(_accidentCameraAnimation.get())->addCameraAttitude(eye,
					osg::Vec3(0,0,0),up);
			}
			ActionData newdata;
			newdata._actionKey = ACTION_NOSWITCH_CAMERAANIMATION;
			newdata._dataType = "AnimationName";
			newdata._userDefineData = &QString("slavecameraanimation");
			_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->enableManipulator();
			dynamic_cast<ControlCenter::CameraAnimationManipulator*>(_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION))
				->setView(NULL);
			_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->setToolAction(&newdata);
			_accidentCameraAnimationIdle = false;
		}
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->frame();
		_manipulatorManager->getManipulatorByMode(CLASS_MANIPULATOR_CAMERAANIMATION)->updateCamera(*_slaveCamera);
	}
}

void SlaveViewEffect::unApply(CoreBase::ActorBase* actor)
{
	if(isIdle())
		return;
	if(_attachObjectEffect.valid() && !_attachObjectEffect->isIdle())
		_attachObjectEffect->unApply(NULL);
	_pv->getViewer()->removeSlave(0);
	//VrDataCore::EffectContainerManager::GetInstance().removeEffectNode(_slaveCamera);
	_pv->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
	VrDataCore::EffectContainerManager::GetInstance().removeEventCallback(VrDataCore::EventType::EVENT_FRAME,this);
	_accidentCameraAnimationIdle = true;
	VrDataCore::EffectBase::unApply(actor);
}